package org.dromara.web.service.impl

import cn.dev33.satoken.stp.parameter.SaLoginParameter
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper
import com.baomidou.mybatisplus.core.toolkit.support.SFunction
import io.github.oshai.kotlinlogging.KLogger
import org.dromara.common.core.constant.Constants
import org.dromara.common.core.constant.GlobalConstants
import org.dromara.common.core.constant.SystemConstants
import org.dromara.common.core.exception.user.CaptchaExpireException
import org.dromara.common.core.exception.user.UserException
import org.dromara.common.core.utils.MessageUtils
import org.dromara.common.core.utils.StringUtils
import org.dromara.common.redis.utils.RedisUtils
import org.dromara.common.satoken.utils.LoginHelper
import org.dromara.system.domain.SysUser
import org.dromara.system.domain.vo.SysClientVo
import org.dromara.system.domain.vo.SysUserVo
import org.dromara.system.mapper.SysUserMapper
import org.dromara.web.service.SysLoginService

/**
 * 认证策略通用方法
 *
 *@author LikeYouDo
 *@date 2025/1/3 15:38
 */

internal fun createSaLoginModel(client: SysClientVo) = SaLoginParameter().apply {
    deviceType = client.deviceType
    // 自定义分配 不同用户体系 不同 token 授权时间 不设置默认走全局 yml 配置
    // 例如: 后台用户30分钟过期 app用户1天过期
    timeout = client.timeout
    activeTimeout = client.activeTimeout
    setExtra(LoginHelper.CLIENT_KEY, client.clientId)
}

/**
 * 校验xx验证码
 */
internal fun validateCode(loginService: SysLoginService, tenantId: String?, way: String, code: String): Boolean {
    val tmpCode = RedisUtils.getCacheObject<String>(GlobalConstants.CAPTCHA_CODE_KEY + way)
    if (StringUtils.isBlank(tmpCode)) {
        loginService.recordLogininfor(
            tenantId,
            way,
            Constants.LOGIN_FAIL,
            MessageUtils.message("user.jcaptcha.expire")
        )
        throw CaptchaExpireException()
    }
    return tmpCode == code
}

/**
 * 查询用户信息
 */
internal fun loadUserByCondition(
    userMapper: SysUserMapper,
    func: SFunction<SysUser, Any>,
    condition: Any,
    log: KLogger
): SysUserVo {
    val user = userMapper.selectVoOne(
        LambdaQueryWrapper(SysUser::class.java).eq(func, condition)
    )
    if (user === null) {
        log.info { "登录用户：$condition 不存在." }
        throw UserException("user.not.exists", condition)
    } else if (SystemConstants.DISABLE == user.status) {
        log.info { "登录用户：$condition 已被停用." }
        throw UserException("user.blocked", condition)
    }
    return user
}
